'use client';

import React, { useState } from 'react';
import clsx from 'clsx';
import { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';
import { CheckIcon } from '@heroicons/react/24/outline';

export interface OptionItem {
  type?: never;
  className?: string;
  label: string;
  value: string | number;
  icon?: React.ReactNode;
  disabled?: boolean;
  onClick?: (option: OptionItem, e: React.MouseEvent<HTMLButtonElement>) => void;
}

export interface DividerItem {
  type: 'divider';
  className?: string;
}

export type Option = OptionItem | DividerItem;

export interface DropdownProps
  extends Omit<React.HTMLProps<HTMLButtonElement>, 'onSelect' | 'onClick' | 'type'> {
  popoverClassName?: string;
  className?: string;
  defaultSelectedKeys?: (string | number)[];
  selectedKeys?: (string | number)[];
  options: Option[];
  children?: React.ReactNode;
  /**
   * 单选模式
   */
  singleMode?: boolean;
  /**
   * 选择后是否自动关闭
   * @default false
   */
  autoClose?: boolean;
  /**
   * 是否显示选中图标，只对单选模式有效，多选默认显示复选框
   * @default false
   */
  showCheckIcon?: boolean;
  /**
   * 是否启用可选中状态
   * @description 如果启用，则会显示复选框或单选框，否则只是普通菜单样式，没有 onSelect 事件
   * @default false
   */
  checkable?: boolean;
  onSelect?: (value: NonNullable<DropdownProps['selectedKeys']>) => void;
  onClick?: (option: OptionItem, e: React.MouseEvent<HTMLButtonElement>) => void;
}

function DropdownNoMemoized(props: DropdownProps) {
  const {
    className,
    popoverClassName,
    defaultSelectedKeys,
    selectedKeys,
    options,
    children,
    singleMode,
    checkable,
    autoClose = false,
    showCheckIcon = false,
    onSelect,
    onClick,
    ...restButtonProps
  } = props;

  const [innerSelectedKeys, setInnerSelectedKeys] = useState(defaultSelectedKeys ?? []);
  const finalSelectedKeys = checkable ? (selectedKeys ?? innerSelectedKeys) : undefined;
  const hasIcon = options.some((option) => 'icon' in option && option.icon); // 检查是否有图标，只有有一个图标，左侧均统一预留图标宽度，保持统一宽度

  return (
    <Popover className={popoverClassName}>
      <PopoverButton
        {...restButtonProps}
        type="button"
        as="button"
        className={clsx('focus:outline-none', className)}
      >
        {children}
      </PopoverButton>
      <PopoverPanel
        transition
        anchor="bottom"
        className={clsx(
          'min-w-20 border shadow-lg rounded-box transition duration-200 ease-in-out z-[999]',
          'bg-base-100 border-gray-200 dark:border-neutral-700',
          '[--anchor-gap:--spacing(1)] data-closed:-translate-y-2 data-closed:opacity-0'
        )}
      >
        {({ close }) => (
          <ul className="menu w-full [--menu-active-bg:var(--color-gray-50)] dark:[--menu-active-bg:var(--color-neutral-900)]">
            {options.map((option, index) => {
              if (option.type === 'divider') {
                return (
                  <div
                    key={index}
                    className={clsx(
                      'border-b border-gray-200 dark:border-neutral-700 mt-[5px] mb-[4.5px]',
                      option.className
                    )}
                  />
                );
              }
              const checked = finalSelectedKeys?.includes(option.value);
              return (
                <li key={option.value} className={clsx(option.disabled && 'menu-disabled')}>
                  <button
                    type="button"
                    className={clsx(
                      'flex items-center justify-between gap-1 w-full text-left overflow-hidden',
                      checkable && singleMode && checked && 'bg-purple-100 dark:bg-purple-800/50'
                    )}
                    disabled={option.disabled}
                    onClick={(e) => {
                      e.stopPropagation();
                      if (!option.disabled) {
                        if (checkable) {
                          if (singleMode) {
                            // 单选模式
                            setInnerSelectedKeys([option.value]);
                            onSelect?.([option.value]);
                          } else {
                            // 多选模式
                            const newSelectedKeys =
                              finalSelectedKeys?.filter((key) => key !== option.value) ?? [];
                            if (!checked) {
                              newSelectedKeys.push(option.value);
                            }
                            setInnerSelectedKeys(newSelectedKeys);
                            onSelect?.(newSelectedKeys);
                          }
                        }
                        const _onClick = option.onClick || onClick;
                        _onClick?.(option, e);
                        if (autoClose) {
                          close();
                        }
                      }
                    }}
                  >
                    {checkable && !singleMode && (
                      <input
                        type="checkbox"
                        className="checkbox checkbox-sm mr-1"
                        checked={checked}
                        readOnly
                      />
                    )}
                    {hasIcon && option.icon && (
                      <div className="inline-flex items-center w-5 flex-none">{option.icon}</div>
                    )}
                    <div className="flex-1 truncate">{option.label}</div>
                    {checkable && singleMode && showCheckIcon && (
                      <span className="inline-flex items-center justify-end w-5 flex-none">
                        {checked && <CheckIcon className="size-3.5" />}
                      </span>
                    )}
                  </button>
                </li>
              );
            })}
          </ul>
        )}
      </PopoverPanel>
    </Popover>
  );
}

export const Dropdown = React.memo(DropdownNoMemoized);
